#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "mergeSort.h"
#include <time.h>

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

//Cria um vetor aleatorio de int com o tamanho especificado.
//Recebe um int com o tamanho. Retorna um ponteiro para int. Esse ponteiro deve
//ser deletado posteriormente.
int* randomArray( int size )
{
    int i; //contador

    //Aloca o array
    int *array = (int*) malloc ( size * sizeof(int) );

    srand(time(NULL)); //Faz com que os numeros pseudo aleatorios sejam gerados a partir da hora atual

    //preenche o vetor com numeros aleatorios
    for ( i = 0; i < size; i++ )
    {
        array[i] = rand()%250;
    }

    return array;
}


//Cria socket e relaciona-o a um endereco.
//Recebe a porta e o endereco do servidor (IP) para a conexao. Retorna o socket.
int make_client_socket(uint16_t port, const char* servIP )
{
    /*Cria socket da familia AF_INET (protocolo da Internet)
    , do tipo SOCK_STREAM (TCP), com o protocolo padrao ( 0 ) */
    int sock = socket( AF_INET, SOCK_STREAM, 0 );

    //Verifica se o socket foi criado. Caso tenha ocorrido algum problema,
    //imprime uma mensagem de erro e sai do programa.
    if ( sock < 0 )
    {
        perror("socket");
        abort();
    }//end if

    //Cria um endereco
    struct sockaddr_in serv_name;

    //Limpa o endereco criado
    bzero( &serv_name, sizeof( serv_name ) );

    //Configura o enderco com os dados fornecidos
    serv_name.sin_family = AF_INET;                 //Protocolo da internet
    serv_name.sin_addr.s_addr = inet_addr(servIP);  //Endereco de ip do servidor
    serv_name.sin_port = htons(port);               //Porta a qual se conectar

    //conecta o socket ao endereco criado
    int n = connect(sock, (struct sockaddr*) &serv_name, sizeof(serv_name));

    //Verifica se a conexao foi bem sucedida
    if ( n < 0 )
    {
        perror( "bind:" );
        abort();
    }//end if

    return sock;
}//end make_client_socket

int main(int argc, char *argv[])
{
    int sockfd, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    struct timeval utime;
    double inicio, inicio2, fim;

    //Comeca a contar o tempo.
    gettimeofday(&utime, NULL);

    inicio = utime.tv_sec + ( utime.tv_usec / 1000000.0 );//tempo antes

    //Cria vetor a ser envidado
    int *oBufferPtr = randomArray(125);
    //aprint("A",oBufferPtr,125);

    int iBuffer[1000];

    //Cria conexao com o servidor na porta 2200
    sockfd = make_client_socket((uint16_t) 2221, "192.168.0.60" );

    inicio2 = utime.tv_sec + ( utime.tv_usec / 1000000.0 );//tempo antes


    //Envia o vetor para o servidor
    n = write( sockfd, oBufferPtr, 125*sizeof(int) );

    //Verifica se ocorreram erros no envio
    if  (n < 0) {error("writing: ");}

    //Verifica se houve algum erro na leitura do socket
    if (n < 0)
         error("ERROR reading from socket");

    //Recebe o vetor ordenado
    n = recv( sockfd, &iBuffer, 1000*sizeof(int), MSG_WAITALL );

    //Verifica se houve algum erro na leitura do socket
    if (n < 0)
         error("ERROR reading from socket");

    //imprime o vetor ordenado na tela
    aprint("FINAL ",iBuffer,1000);


    //deleta o vetor alocado
    free(oBufferPtr);

    //fecha a conexao
    close(sockfd);

    //atualiza a hora do sistema
    gettimeofday(&utime, NULL);

    fim = utime.tv_sec + ( utime.tv_usec / 1000000.0 );//tempo final

    //imprime o tempo de conexao
    printf(" Tempo de total:  %.10fs\n", fim - inicio);
    return 0;
}
